﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Core
{
    public class Chainer
    {
        protected Dictionary<int, Chain> openedByThreadId;
        protected Dictionary<int, Chain> openedBySerial;

        protected List<Chain> closedChains;
        public List<Chain> ClosedChains { get { return closedChains; } }

        public Chainer()
        {
            closedChains = new List<Chain>();
            openedBySerial = new Dictionary<int, Chain>();
            openedByThreadId = new Dictionary<int, Chain>();
        }

        public void OpenChain(ServiceLine line)
        {
            Chain opened = GetChainOpenedByThreadId(line);
            if (opened != null)
                CloseChain(opened);
            Chain chain = new Chain(line);
            OpenByThreadId(line, chain);
        }

        private void CloseChain(Chain opened)
        {
            closedChains.Add(opened);
        }

        private void OpenByThreadId(ServiceLine line, Chain chain)
        {
            openedByThreadId[line.ThreadId] = chain;
        }

        private void OpenBySerial(int serial, Chain chain)
        {
            openedBySerial[serial] = chain;
        }

        private Chain GetChainOpenedByThreadId(ServiceLine line)
        {
            return openedByThreadId.ContainsKey(line.ThreadId) ? openedByThreadId[line.ThreadId] : null;
        }

        private Chain GetChainOpenedBySerial(ProtocolLine line)
        {
            return openedBySerial.ContainsKey(line.Serial) ? openedBySerial[line.Serial] : null;
        }

        public void AppendToChain(ServiceLine line)
        {
            Chain opened = GetChainOpenedByThreadId(line);
            if (opened == null)
            {
                Chain chain = new Chain(line);
                OpenByThreadId(line, chain);
            }
            else
            {
                opened.Add(line);
            }
        }

        public void AppendToChain(ProtocolLine line)
        {
            Chain opened = GetChainOpenedBySerial(line);
            if (opened == null)
            {
                Chain chain = new Chain(line);
                OpenBySerial(line.Serial, chain);
            }
            else
            {
                opened.Add(line);
            }
        }

        public void AppendToChainBySession(ServiceLine line, int sessionId)
        {
            Chain opened = GetChainOpenedByThreadId(line);
            if (opened == null)
            {
                Chain chain = new Chain(line);
                OpenByThreadId(line, chain);
                OpenBySerial(sessionId, chain);
            }
            else
            {
                OpenBySerial(sessionId, opened);
                opened.Add(line);
            }
        }
    }
}
